package redis

import (
	"context"
	_ "embed"
	"github.com/redis/go-redis/v9"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"time"
)

type FixWindowBuilder struct {
	client      *redis.Client
	size        time.Duration
	rate        int
	serviceName string
}

func NewFixWindowBuilder(client *redis.Client, size time.Duration, rate int, serviceName string) *FixWindowBuilder {
	return &FixWindowBuilder{
		client:      client,
		size:        size,
		rate:        rate,
		serviceName: serviceName,
	}
}

func (f *FixWindowBuilder) Build() grpc.UnaryServerInterceptor {
	return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
		var limit string
		limit, err = f.limit(ctx)
		if limit == "true" {
			return nil, status.Error(codes.ResourceExhausted, "fixWindow: limit exceeded")
		}
		return handler(ctx, req)
	}
}

//go:embed lua/fix_window.lua
var fixWindowLua string

func (f *FixWindowBuilder) limit(ctx context.Context) (string, error) {
	val, err := f.client.Eval(ctx, fixWindowLua, []string{f.serviceName}, f.rate, f.size.Milliseconds()).Result()
	if err != nil {
		return "false", err
	}
	return val.(string), nil
}
